文章目录
现在大部分的主流网站都用JavaScript动态显示网页内容,这样使得我们之前提取技术无法正常运行。本篇将介绍两种提取基于JS动态网页的数据。
- JavaScript逆向工程
- 渲染JavaScript
1.动态网页示例
我们先看一个动态网页的示例。在示例网站的中,我们从http://127.0.0.1:8000/places/default/search 搜索国家名包涵A
的表单。
我们根据按F12
开发者工具显示的标签,用lxml模块提取数据,发现提取不到什么数据。
>>> import lxml.html
>>> from downloader import Downloader
>>> D=Downloader()
>>> html=D('http://127.0.0.1:8000/places/default/search')
Downloading: http://127.0.0.1:8000/places/default/search
>>> tree=lxml.html.fromstring(html)
>>> tree.cssselect('div#result a')
[]
>>>
我们在浏览器右击查看网页源代码发现我们要提取的div数据是空的。
...
<div id="results">
</div>
...
这是因为F12
的开发者工具是显示的标签是网页当前的状态,也就是使用JavaScript动态加载完搜索结果之后的网页。
2.对加载内容进行逆向工程
由于这些网页的数据是JS动态加载的,要想提取该数据,我们需要网页如何加载该数据的,该过程也被称为逆向工程。
2.1通过开发者工具的逆向工程
我们在上节F12
的开发者工具的Network
发现AJAX响应一个json文件,即:http://127.0.0.1:8000/places/ajax/search.json?&search_term=A&page_size=10&page=0 。AJAX响应的返回数据是JSON格式的,因此我们可以使用Python的json模块将解析为一个字典。
>>> import json
>>> html=D('http://127.0.0.1:8000/places/ajax/search.json?&search_term=A&page_size=10&page=0')
Downloading: http://127.0.0.1:8000/places/ajax/search.json?&search_term=A&page_size=10&page=0
>>> json.loads(html)
{u'records': [
{u'pretty_link': u'<div><a href="/places/default/view/Afghanistan-1"><img src="/places/static/images/flags/af.png" /> Afghanistan</a></div>', u'country': u'Afghanistan', u'id': 3781},
{u'pretty_link': u'<div><a href="/places/default/view/Aland-Islands-2"><img src="/places/static/images/flags/ax.png" /> Aland Islands</a></div>', u'country': u'Aland Islands', u'id': 3782},...],
u'num_pages': 22,
u'error': u''}
>>>
我们可以通过分页请求提取json数据存到txt文件中。分页请求会让同一个国家在多次搜索返回多次,但通过set()
集合会过滤重复的元素。
# -*- coding: utf-8 -*-
import json
import string
import downloader
def main():
template_url = 'http://127.0.0.1:8000/places/ajax/search.json?&page={}&page_size=10&search_